from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
from sklearn.datasets import make_blobs

import matplotlib.pyplot as plt
import matplotlib.cm as cm          # matplotlib.cm 色谱
import numpy as np

# 构造模型数据
X, y = make_blobs(n_samples=5000
                  ,n_features=2     # 特征数
                  ,centers=10        # 中心
                  ,random_state=1
                  )
# 真实分类可视化
colors_y = cm.nipy_spectral(y / 10)    # 设置颜色
plt.scatter(X[:,0],X[:,1],c="black")
plt.show()
plt.scatter(X[:,0],X[:,1],c=colors_y)
plt.show()
# 发现当数据的centers越来越大时，不同的centers会更混在一起，这样划分起来会更困难。或者说实际中聚类的簇数是应该会少于centers的。

# 测试n_clusters
# n_clusters=5
# clusters=KMeans(n_clusters).fit(X)
# cluster_labels=clusters.labels_
# colors_kmeans = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)    # 设置颜色
# plt.scatter(X[:,0],X[:,1],c=colors_kmeans)
# plt.show()

# inertia=clusters.inertia_
# print(inertia)
# centroid = clusters.cluster_centers_     # 簇心的特征值
# print(centroid)
#
# silhouette_avg = silhouette_score(X, cluster_labels)    # 轮廓系数均值
# print(silhouette_avg)
# sample_silhouette_values = silhouette_samples(X, cluster_labels)    # 每个样本的轮廓系数值
# print(sample_silhouette_values)


# 果然，只看inertia和silhouette_avg是无法判断最佳n_clusters的。还是要可视化
# for i in range(2,15):
#     n_clusters = i
#     clusters = KMeans(n_clusters).fit(X)
#     cluster_labels = clusters.labels_
#     inertia=clusters.inertia_
#     silhouette_avg = silhouette_score(X, cluster_labels)
#     print("n_clusters=%d，inertia=%f,silhouette_avg=%f"% (i , inertia , silhouette_avg))


# 使用循环观察各种n_clusters的结果。
# 从可视化上其实也很难找到一个明显优于其他的。即使n_clusters和设置的center一致，也看不出明显更好。还是根据实际业务需要取划分比较好，而且n_clusters实际中应该不会太大
for i in range(3,15):
    n_clusters = i
    fig, (ax1, ax2) = plt.subplots(1, 2)
    fig.set_size_inches(18, 7)
    ax1.set_xlim([-0.1, 1])
    ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])
    clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
    cluster_labels = clusterer.labels_
    silhouette_avg = silhouette_score(X, cluster_labels)
    print("For n_clusters =", n_clusters,
          "The average silhouette_score is :", silhouette_avg)
    sample_silhouette_values = silhouette_samples(X, cluster_labels)
    y_lower = 10
    for i in range(n_clusters):
        ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
        ith_cluster_silhouette_values.sort()
        size_cluster_i = ith_cluster_silhouette_values.shape[0]
        y_upper = y_lower + size_cluster_i
        color = cm.nipy_spectral(float(i)/n_clusters)
        ax1.fill_betweenx(np.arange(y_lower, y_upper)
                         ,ith_cluster_silhouette_values
                         ,facecolor=color
                         ,alpha=0.7
                         )
        ax1.text(-0.05
                 , y_lower + 0.5 * size_cluster_i
                 , str(i))
        y_lower = y_upper + 10
    ax1.set_title("The silhouette plot for the various clusters.")
    ax1.set_xlabel("The silhouette coefficient values")
    ax1.set_ylabel("Cluster label")
    ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
    ax1.set_yticks([])
    ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
    colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
    ax2.scatter(X[:, 0], X[:, 1]
               ,marker='o' #点的形状
               ,s=8 #点的大小
               ,c=colors
               )
    centers = clusterer.cluster_centers_
    ax2.scatter(centers[:, 0], centers[:, 1], marker='x',
                c="red", alpha=1, s=200)
    ax2.set_title("The visualization of the clustered data.")
    ax2.set_xlabel("Feature space for the 1st feature")
    ax2.set_ylabel("Feature space for the 2nd feature")
    plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
                  "with n_clusters = %d" % n_clusters),
                 fontsize=14, fontweight='bold')
    plt.show()
